﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ActionTrackerDAO.Base;
using ActionTrackerEntities;

namespace ActionTrackerDAO
{
    public class AccionDAO : DAOBase<Accion, int>
    {
        public List<Accion> GetByFiltro(int? pIdUsuario, int? pIdReunion, int? pIdProyecto,
                                        EstadoAccionEnum? pEstadoAccion)
        {
            var oQuery = Session.QueryOver<Accion>();
            Session.Clear();
            if (pIdUsuario.HasValue)
            {
                oQuery.Where(x => x.Usuario.IdUsuario == pIdUsuario);
            }
            if (pIdReunion.HasValue)
            {
                oQuery.Where(x => x.Reunion.IdReunion == pIdReunion);
            }
            if (pIdProyecto.HasValue)
            {
                oQuery.Where(x => x.Proyecto.IdProyecto == pIdProyecto);
            }
            if (pEstadoAccion.HasValue)
            {
                oQuery.Where(x => x.EstadoAccion == (int) pEstadoAccion);
            }

            return (List<Accion>) oQuery.OrderBy(x => x.FechaInicio).Asc.List();
        }

        public List<Accion> GetByReporteAccionesVencidas(DateTime pFecha, int pIdProyecto)
        {
            var oQuery = Session.QueryOver<Accion>();
            Session.Clear();
            oQuery.Where(x => x.FechaVencimiento < pFecha)
                .And(x => x.FechaFin == null)
                .And(x => x.Proyecto.IdProyecto == pIdProyecto);

            return (List<Accion>) oQuery.OrderBy(x => x.FechaInicio).Asc.List();
        }

        public List<MetricaPromedio> GetMetricasPromedioUsuario(int tipoMetrica, int? mes, int? anio, int idProyecto)
        {
            var oQuery = Session.QueryOver<Accion>().List();
            var oQuery1 = Session.QueryOver<Usuario>();
            Session.Clear();
            var miProyecto = Session.QueryOver<Proyecto>().Where(x => x.IdProyecto == idProyecto).List().FirstOrDefault();
            List<Usuario> misUsuarios = new List<Usuario>();
            misUsuarios = miProyecto.Usuarios.ToList();

            List<Accion> listaAcciones = oQuery.Where(x => x.EstadoAccion == 3).Where(x => x.IdProyecto == idProyecto).ToList();
            var listaUsuarios = oQuery1.List();
            var lista = new List<MetricaPromedio>();

            switch (tipoMetrica)
            {
                case 1:
                    listaAcciones = listaAcciones.Where(x => x.EstadoAccion == 3).Where(x => x.FechaFin.Value.Year == anio.Value).ToList();
                    break;
                case 2:
                    listaAcciones = listaAcciones.Where(x => x.EstadoAccion == 3).Where(x => x.FechaFin.Value.Month == mes.Value).ToList();
                    break;
                case 3:
                    listaAcciones = listaAcciones.Where(x => x.EstadoAccion == 3).ToList();
                    break;
            }

            foreach (var usuario in misUsuarios)
            {
                var oMetricaPromedio = new MetricaPromedio();
                oMetricaPromedio.EjeX = usuario.Nombre;
                foreach (var entidad in listaAcciones)
                {
                    if(entidad.IdUsuario == usuario.IdUsuario)
                    {
                        oMetricaPromedio.Acumulacion += int.Parse(entidad.FechaFin.Value.AddDays(1).Subtract(entidad.FechaInicio.Value).TotalDays.ToString());
                        oMetricaPromedio.Cantidad++;
                    }
                }
                if(oMetricaPromedio.Cantidad!=0)
                {
                    oMetricaPromedio.Promedio = oMetricaPromedio.Acumulacion / oMetricaPromedio.Cantidad;
                }
                else
                {
                    oMetricaPromedio.Promedio = 0;
                }
                lista.Add(oMetricaPromedio);
            }
            
            return lista;
        }

        public List<MetricaCantidad> GetMetricasCantidadUsuario(int tipoMetrica, int? mes, int? anio, int idProyecto)
        {
            var oQuery = Session.QueryOver<Accion>().List();
            var oQuery1 = Session.QueryOver<Usuario>();
            Session.Clear();
            var miProyecto = Session.QueryOver<Proyecto>().Where(x => x.IdProyecto == idProyecto).List().FirstOrDefault();
            List<Usuario> misUsuarios = new List<Usuario>();
            misUsuarios = miProyecto.Usuarios.ToList();

            List<Accion> listaAcciones = oQuery.Where(x => x.IdProyecto == idProyecto).ToList();
            var listaUsuarios = oQuery1.List();
            var lista = new List<MetricaCantidad>();

            switch (tipoMetrica)
            {
                case 1:
                    listaAcciones = listaAcciones.Where(x => x.FechaInicio.Value.Year == anio.Value).ToList();
                    break;
                case 2:
                    listaAcciones = listaAcciones.Where(x => x.FechaInicio.Value.Month == mes.Value).ToList();
                    break;
                case 3:
                    listaAcciones = listaAcciones.ToList();
                    break;
            }

            foreach (var usuario in misUsuarios)
            {
                var oMetricaCantidad = new MetricaCantidad();
                oMetricaCantidad.EjeX = usuario.Nombre;
                foreach (var entidad in listaAcciones)
                {
                    if (entidad.IdUsuario == usuario.IdUsuario)
                    {
                        oMetricaCantidad.Cantidad++;
                    }
                }
                lista.Add(oMetricaCantidad);
            }
            return lista;
        }

        public List<MetricaCantidad> GetMetricasCantidadUsuario()
        {
            var oQuery = Session.QueryOver<Accion>();
            var oQuery1 = Session.QueryOver<Usuario>();
            Session.Clear();
            var listaAcciones = oQuery.Where(x => x.EstadoAccion == 3).List();
            var listaUsuarios = oQuery1.List();
            var lista = new List<MetricaCantidad>();

            foreach (var usuario in listaUsuarios)
            {
                var oMetricaCantidad = new MetricaCantidad();
                oMetricaCantidad.EjeX = usuario.Nombre;
                foreach (var entidad in listaAcciones)
                {
                    if (entidad.IdUsuario == usuario.IdUsuario)
                    {
                        oMetricaCantidad.Cantidad++;
                    }
                }
                lista.Add(oMetricaCantidad);
            }
            return lista;
        }

        public List<MetricaCantidad> GetMetricasCantidadAnio()
        {
            var oQuery = Session.QueryOver<Accion>();
            Session.Clear();
            var listaAcciones = oQuery.Where(x => x.EstadoAccion == 3).List();
            var listaAnio = new List<Accion>();

            var lista = new List<MetricaCantidad>();
            foreach (var accion in listaAcciones)
            {
                bool existe = false;
                foreach (var anio in listaAnio)
                {
                    if (anio.FechaInicio.Value.Year == accion.FechaInicio.Value.Year)
                    {
                        existe = true;
                    }
                }
                if (!existe)
                {
                    listaAnio.Add(accion);
                }
            }

            foreach (var anio in listaAnio)
            {
                var oMetricaCantidad = new MetricaCantidad();
                oMetricaCantidad.EjeX = anio.FechaInicio.Value.Year.ToString();
                foreach (var entidad in listaAcciones)
                {
                    if (entidad.FechaInicio.Value.Year == anio.FechaInicio.Value.Year)
                    {
                        oMetricaCantidad.Cantidad++;
                    }
                }
                lista.Add(oMetricaCantidad);
            }

            return lista;
        }

        public List<MetricaCantidad> GetMetricasCantidadMes()
        {
            var oQuery = Session.QueryOver<Accion>();
            Session.Clear();
            var listaAcciones = oQuery.Where(x => x.EstadoAccion == 3).List();
            var listaMes = new List<Accion>();

            var lista = new List<MetricaCantidad>();
            foreach (var accion in listaAcciones)
            {
                bool existe = false;
                foreach (var mes in listaMes)
                {
                    if (mes.FechaInicio.Value.Month == accion.FechaInicio.Value.Month)
                    {
                        existe = true;
                    }
                }
                if (!existe)
                {
                    listaMes.Add(accion);
                }
            }

            foreach (var anio in listaMes)
            {
                var oMetricaCantidad = new MetricaCantidad();
                oMetricaCantidad.EjeX = GetMes(anio.FechaInicio.Value.Month);
                foreach (var entidad in listaAcciones)
                {
                    if (entidad.FechaInicio.Value.Month == anio.FechaInicio.Value.Month)
                    {
                        oMetricaCantidad.Cantidad++;
                    }
                }
                lista.Add(oMetricaCantidad);
            }
            return lista;
        }

        #region Soporte

        public string GetMes(int mes)
        {
            switch (mes)
            {
                case 1:
                    return "Enero";
                case 2:
                    return "Febrero";
                case 3:
                    return "Marzo";
                case 4:
                    return "Abril";
                case 5:
                    return "Mayo";
                case 6:
                    return "Junio";
                case 7:
                    return "Julio";
                case 8:
                    return "Agosto";
                case 9:
                    return "Septiembre";
                case 10:
                    return "Octubre";
                case 11:
                    return "Noviembre";
                case 12:
                    return "Diciembre";
            }
            return " ";
        }

        public List<Accion> GetAniosOMeses(int tipoMetricaPromedio)
        {
            var oQuery = Session.QueryOver<Accion>();
            var listaAcciones = oQuery.Where(x => x.EstadoAccion == 3).List();
            var listaAniosOMesesAcciones = new List<Accion>();
            switch (tipoMetricaPromedio)
            {
                case 1:
                    foreach (var accion in listaAcciones)
                    {
                        bool existe = false;
                        foreach (var anio in listaAniosOMesesAcciones)
                        {
                            if (anio.FechaFin.Value.Year == accion.FechaFin.Value.Year)
                            {
                                existe = true;
                            }
                        }
                        if (!existe)
                        {
                            listaAniosOMesesAcciones.Add(accion);
                        }
                    }
                    return listaAniosOMesesAcciones;
                case 2:
                    foreach (var accion in listaAcciones)
                    {
                        bool existe = false;
                        foreach (var mes in listaAniosOMesesAcciones)
                        {
                            if (mes.FechaFin.Value.Month == accion.FechaFin.Value.Month)
                            {
                                existe = true;
                            }
                        }
                        if (!existe)
                        {
                            listaAniosOMesesAcciones.Add(accion);
                        }
                    }
                    return listaAniosOMesesAcciones;
             }
            return null;
        }

        public bool ExisteAccionConNombre(string pDescripcion, int pProyectoId, int? pIdAccionEnEdicion)
        {
            if (pIdAccionEnEdicion.HasValue)
            {
                Session.Clear();
                //busco la acción en la BD
                var oAccionEnEdicion = Session.QueryOver<Accion>()
                .Where(x => x.IdAccion == pIdAccionEnEdicion)
                .Where(x => x.Proyecto.IdProyecto == pProyectoId)
                .List().FirstOrDefault();

                //si el nombre que está en BD es igual al parámetro, no cambié el nombre de la acción
                if (oAccionEnEdicion.Descripcion == pDescripcion)
                {
                    return false;
                }
            }

            var oQuery = Session.QueryOver<Accion>()
            .Where(x => x.Descripcion == pDescripcion)
            .Where(x => x.Proyecto.IdProyecto == pProyectoId)
            .List();

            if (oQuery.Count > 0)
            {
                return true;
            }
            return false;
        }

        #endregion
        
    }
}